/*
*  Circle2D.cpp
*
*  Created on: Jan 17, 2012
*  
*/

#pragma region INCLUDEs
//
#include  "Circle2D.h"
#include "Box2D.h"
#include "MathHelper.h"

#include <iostream>
using namespace std;

#pragma endregion 




namespace Physics
{
	//Re-Declare static variable for Compiler Pre-Processing
	int Circle2D::cir2D_InstanceCount = 0;

#pragma region CONSTRUCTORs
	//C001: DEFAULT Constructor
	Circle2D::Circle2D()
	{
		this->radius = 1;

		this->objID = ZERO;
		++cir2D_InstanceCount;
	}	
	
	//C002: Overloaded Constructor
	Circle2D::Circle2D(const float radius, const Vector2 &pos = Vector2() )
	{
		this->radius = ( radius < 1 ) ? 1 : radius;
		this->position = pos;

		this->objID = ZERO;
		++cir2D_InstanceCount;
	}

	//C003: Overloaded Constructor
	Circle2D::Circle2D(const float radius, const Vector2 &pos = Vector2(), const Vector2 &dir = Vector2() )
	{
		this->radius = ( radius < 1 ) ? 1 : radius;
		this->position = pos;
		this->direction = dir;

		this->objID = ZERO;
		++cir2D_InstanceCount;
	}

	//C004: Overloaded Constructor
	Circle2D::Circle2D(const float radius, const Vector2 &pos = Vector2(), const Vector2 &dir = Vector2(), const float speed = 0, const float mass = 0 )
	{
		this->radius = ( radius < 1 ) ? 1 : radius;
		this->position = pos;
		this->direction = dir;

		this->speed = speed;
		this->mass = mass;

		this->objID = ZERO;
		++cir2D_InstanceCount;
	}

	//C005: COPY Constructor
	Circle2D::Circle2D( const Circle2D &circle )
	{
		this->radius = circle.getRadius();
		this->position = circle.getPosition();
		this->direction = circle.getDirection();

		this->speed = circle.getSpeed();
		this->mass = circle.getMass();

		this->objID = circle.getID();
		++cir2D_InstanceCount;
	}

	//C006: Assignment Operator
	Circle2D& Circle2D::operator=( const Circle2D &circle )
	{
		if ( this != &circle )
		{
			this->radius = circle.getRadius();
			this->position = circle.getPosition();
			this->direction = circle.getDirection();

			this->speed = circle.getSpeed();
			this->mass = circle.getMass();

			this->objID = circle.getID();
			++cir2D_InstanceCount;
		}
		return *this;
	}
	
	//C007: Virtual Destructor
	Circle2D::~Circle2D() 
	{ 
		//decrement global active objects' counter
		IPhysicsObject::decrement_ObjectCount(); 

		//decrement circle2D Instance Counter
		( ( cir2D_InstanceCount > 0 ) ? --cir2D_InstanceCount : cir2D_InstanceCount = 0 );
	}
#pragma endregion


	//M012: Getter Instance Count
	const int Circle2D::count()
	{
		return cir2D_InstanceCount;
	}


#pragma region RADIUS_PROPERTIES
	//M001: Setter Radius
	void Circle2D::setRadius(const float radius)
	{
		this->radius = ( ( radius < 1 ) ?  1 : radius );
	}

	//M002: Getter Radius
	const float Circle2D::getRadius() const  { return this->radius; }
	//
#pragma endregion


#pragma region IPhysicsObject_2D_METHODs
	//M013: Print Summary Info about instance object
	void Circle2D::Info()
	{
		cout << "\n======================================================\n" << endl;
		cout << "\nCircle2D Obj Info:\n" << endl;
		cout << "\n--------------------------------------------------------\n" << endl;

		cout << "Object ID: " << this->objID << endl << endl;

		cout << "Position XY: (" << this->position.getX() << ", " << this->position.getY() << ")" << endl;
		cout << "Direction XY: (" << this->direction.getX() << ", " << this->direction.getY() << ")" << endl;
		cout << "Speed: " << this->speed << endl;
		cout << "Mass: " << this->mass << endl;

		cout << "Radius: " << this->radius << endl;
	}
#pragma endregion


#pragma region ICOLLISION_2D_METHODS
	//M003: THIS -> Box2D collision check
	bool Circle2D::collision(const Box2D &box)
	{
		Vector2 center = this->getCenter();

		float sqrDist = MathHelper::sqrDistancePointToBox(center, box);
		float sqrRadius =this->radius * this->radius;

		return ( (sqrDist > sqrRadius) ? false : true );
	}

	//M004: THIS -> Circle2D collision check
	bool Circle2D::collision(const Circle2D &circle)
	{
		float dist = MathHelper::findDistance( this->getCenter(), circle.getCenter() );

		return ( dist <= (this->getRadius() + circle.getRadius()) ) ? true : false;
	}
#pragma endregion


#pragma region Shape2D_Re-DEFINE_METHODS_AGAIN
	//M005: Getter Center
	const Vector2 Circle2D::getCenter() const
	{
		return this->position;
	}


	//==================== SETTER: ROTATION_2D ====================
	//
	//M006: Rotate 2D shape using degrees
	void Circle2D::rotateInDegs(const float degrees)
	{
		Vector2 vec = MathHelper::degreesToVector2(degrees);
		vec = (vec + this->direction);
		vec.normalize();
		this->direction = vec;
	}

	//M007: Rotate 2D shape using radians
	void Circle2D::rotateInRads(const float radians)
	{
		Vector2 vec = MathHelper::radiansToVector2(radians);
		vec = (vec + this->direction);
		vec.normalize();
		this->direction = vec;
	}
	//==================== SETTER: ROTATION_2D ====================


	//==================== SETTER: TRANSLATION_2D ====================
	//
	//-------------------------------------------------
	//		TRANSLATION_POSITION
	//-------------------------------------------------
	//
	//M008: Translate position using floats
	void Circle2D::translatePosition(const float X, const float Y)
	{
		this->position.setXY( this->position.getX() + X, this->position.getY() + Y );
	}

	//M009: Translate position using Vector2
	void Circle2D::translatePosition(const Vector2 &value)
	{
		this->position.setXY( this->position + value );
	}


	//-------------------------------------------------
	//		TRANSLATION_DIRECTION
	//-------------------------------------------------
	//
	//M010: Translate direction using floats
	void Circle2D::translateDirection(const float X, const float Y)					
	{
		Vector2 vec(X, Y);
		vec = (vec + this->direction);
		vec.normalize();
		this->direction = vec;
	}

	//M011: Translate direction using Vector2
	void Circle2D::translateDirection(const Vector2 &value)						
	{
		Vector2 vec = value;
		vec = (vec + this->direction);
		vec.normalize();
		this->direction = vec;
	}

	//==================== SETTER: TRANSLATION_2D ====================
#pragma endregion

} /* NAMESPACE */
